package com.example.springboottest.example.copyonwrite;

import com.example.springboottest.util.Print;
import org.junit.Test;

import java.util.ArrayList;
import java.util.Collections;
import java.util.Iterator;
import java.util.List;
import java.util.concurrent.CopyOnWriteArrayList;

import static com.example.springboottest.util.BeanUtil.asList;
import static com.example.springboottest.util.ThreadUtil.sleepSeconds;
import static java.lang.Thread.currentThread;

/**
 * 写时复制
 * CopyOnWrite（写时复制）就是在修改器对一块内存进行修改时， 不直接在原有内存块上进行写操作，
 * 而是将内存复制一份，在新的内存 中进行写操作，写完之后，
 * 再将原来的指针（或者引用）指向新的内 存，原来的内存被回收。
 */
public class CopyOnWriteArrayListTest {
    //并发操作的任务目标
    public static class CocurrentTarget implements Runnable {
        //并发操作的目标队列
        List<String> targetList = null;

        public CocurrentTarget(List<String> targetList) {
            this.targetList = targetList;
        }

        @Override
        public void run() {
            Iterator<String> iterator = targetList.iterator();
            //迭代操作
            while (iterator.hasNext()) {
                // 在迭代操作时，进行列表的修改
                String threadName = currentThread().getName();
                Print.tco("元素：" + iterator.next());
                Print.tco("开始往同步队列加入线程名称：" + threadName);
                sleepSeconds(1);
                targetList.add(threadName);
            }
        }
    }

    //测试同步队列：在迭代操作时，进行列表的修改  会抛出UnsupportedOperationException异常
    @Test
    public void testSynchronizedList() {
        List<String> notSafeList = asList("a", "b", "c");
        List<String> synList = Collections.synchronizedList(notSafeList);

        CocurrentTarget synchronizedListListDemo = new CocurrentTarget(synList);
        //10个线程并发
        for (int i = 0; i < 10; i++) {
            new Thread(synchronizedListListDemo, "线程" + i).start();
        }
        //主线程等待
        sleepSeconds(1000);
    }

    //测试CopyOnWriteArrayList
    @Test
    public void testcopyOnWriteArrayList() {
        List<String> notSafeList = asList("a", "b", "c");

        //创建一个  CopyOnWriteArrayList 队列
        List<String> copyOnWriteArrayList = new CopyOnWriteArrayList();
        copyOnWriteArrayList.addAll(notSafeList);

        //并发操作目标
        CocurrentTarget copyOnWriteArrayListDemo = new CocurrentTarget(copyOnWriteArrayList);
        for (int i = 0; i < 1; i++) {
            new Thread(copyOnWriteArrayListDemo, "线程" + i).start();
        }
        //主线程等待
        sleepSeconds(1000);
    }

    /**
     * 测试fn
     * 普通list在通过迭代器遍历时，是不能添加或删除的
     * 但是copyOnWrite可以做到
     */
    @Test
    public void testArrayList() {
        List<String> notSafeList = new ArrayList<>();
        notSafeList.add("a");
        notSafeList.add("b");
        notSafeList.add("c");
        List<String> copyOnWriteArrayList = new CopyOnWriteArrayList();
        copyOnWriteArrayList.addAll(notSafeList);

//        Iterator<String> it = notSafeList.listIterator();
        Iterator<String> it = copyOnWriteArrayList.listIterator();
        while (it.hasNext()) {
            System.out.println(it.next());
//            notSafeList.add("111");
            copyOnWriteArrayList.add("111");
        }
        //主线程等待
//        sleepSeconds(1000);
    }
}
